package routing;

import geocoding.CustomNodes;

import java.util.ArrayList;
import java.util.HashSet;

import org.osmdroid.views.overlay.MyLocationOverlay;

import osm.OsmReader;
import urnav.example.com.URNavActivity;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;

public class TripControl {
	
	boolean isFinished=false;
	int checkNodeID;
	int nextNodeID;
	int currentNodeID;
	int currentNodePosition;
	int nextNodePosition=1;
	int targetNodeID;
	int position=0;
	String TAG="URNav";
	private Handler myHandler = new Handler();
	boolean finish=false; 
	private HashSet <String> shownLandmarks = new HashSet<String>();  
	
	ArrayList<Node> segmentStarts = new ArrayList<Node>();
	ArrayList<Segment> segments = new ArrayList<Segment>(); 
	MyLocationOverlay myLocOverlay; 
	CustomNodes cn = new CustomNodes();  
	Trip myTrip = new Trip(); 
	int currentSegment = -1; 
	
	
	
	

	
	public void checkTripLandMarkMode(MyLocationOverlay myLocOverlay, CustomNodes cn, int targetNodeID, Trip myTrip,
			Handler myHandler, TextView myText, long lastLMtime, TextView debug){

		
			if (checkForDestination (cn, myLocOverlay, myTrip)==true) {
				update(myHandler, currentNodePosition, myTrip, 0, "", true, false);;
			}
		
			checkCurrentSegmentTest();
			
			Log.d(TAG, "current Segment: " + currentSegment);
			
			

			
			
	}
	
	
	public void checkTripSimpleMode(MyLocationOverlay myLocOverlay, CustomNodes cn, int targetNodeID, Trip myTrip, Handler myHandler, TextView myText){
		checkForDestination (cn, myLocOverlay, myTrip);
		currentNodePosition=myTrip.getCurrentNode3();
		currentNodeID=myTrip.getTripItem(currentNodePosition);
		
		update(myHandler, currentNodePosition, myTrip, 0, "", finish, false);
	
		Location thisLocation=myLocOverlay.getLastFix();
		checkItems (cn, myTrip, thisLocation);
		showDistance(cn, myTrip, myLocOverlay, myText, currentNodePosition);		
		
		
	}
		
		
		public void showDistance(CustomNodes cn, Trip myTrip, MyLocationOverlay myLocOverlay, TextView myText, int currentNodePosition){
			if (!(currentNodePosition==myTrip.getTripList().size()-1)) {
				Location thisLocation=myLocOverlay.getLastFix();
				
				if (thisLocation == null) {
					return; 
				}
				
				Location nextLocation=new Location("x");
				
				int nextNodeID=myTrip.getTripItem(currentNodePosition+1);
	
				nextLocation.setLatitude(cn.getDlati(nextNodeID));
				nextLocation.setLongitude(cn.getDlongi(nextNodeID));
				
				int distance;
				float fdistance= thisLocation.distanceTo(nextLocation);
				distance = (int)fdistance;
				
				nextNodePosition=currentNodePosition+1;
				Compass myCompass = new Compass();
				
				
				
				myText.setText("Noch " + distance + " Meter Richtung " + myCompass.getOrientation(thisLocation, nextLocation));
			}
		}
		
		

		
		
public String showLandmarks (int currentNodePosition, Trip myTrip, CustomNodes cn, Location thisLocation) {
			int bestlmID = getBestLandmark(cn, myTrip, currentNodePosition, thisLocation);
			
			Log.d(TAG, "XXX showLandmarks");
			
			for (int k=0; k<cn.getValueSize(bestlmID); k++) {
				Log.i(TAG, "BestLM: " + cn.getTag(bestlmID, k) + " " + cn.getValue(bestlmID, k));
			}

			String output =  "";
			if (!(bestlmID==0)) {
			boolean newlm =false; 
			for (int i=0; i<cn.getValueSize(bestlmID); i++) {
				
				if ((cn.getTag(bestlmID, i).equals("historic"))  
						|| (cn.getTag(bestlmID, i).equals("natural")) 
						|| (cn.getTag(bestlmID, i).equals("tourist"))
						|| (cn.getTag(bestlmID, i).equals("building"))		
						|| (cn.getTag(bestlmID, i).equals("shop"))) { 
					newlm=true;
					Log.d(TAG, "newLM == true");
					Compass myCompass = new Compass();
					Location nextLocation=new Location("x");
					
					int nextNodeID=myTrip.getTripItem(currentNodePosition+1);
		
					nextLocation.setLatitude(cn.getDlati(nextNodeID));
					nextLocation.setLongitude(cn.getDlongi(nextNodeID));
					output=output.concat(myCompass.getDirection(thisLocation, bestlmID, myTrip.getTripItem(currentNodePosition+1), cn) + " vorbei an: ");
					output=output.concat(cn.getTag(bestlmID, i) + " " + cn.getValue(bestlmID, i) + " ");
				
				}

			}
			
			for (int j=0; j<cn.getValueSize(bestlmID); j++) {
				if ((newlm==true) && cn.getTag(bestlmID, j).equals("name")) {
					
					String name = cn.getValue(bestlmID, j); 
					
					
					Log.d(TAG, "shownLandmarks: " + shownLandmarks.toString());
					
					if (!shownLandmarks.contains(name) && !URNavActivity.openActivity) {
						shownLandmarks.add(name);
						Log.d(TAG, "is Not in shownLandmarks");
					}
					
					else {
						Log.d(TAG, "is Already in shownLandmarks");
						return ""; 
					}
					
					output=output.concat(" " + cn.getValue(bestlmID, j));
					
				}
			}
			}

			return output;
		}
		

		
		

		
//		Returns the Landmark for this currentPosition
		public int getBestLandmark (CustomNodes cn, Trip myTrip, int currentNodePosition, Location thisLocation) {	

			
			ArrayList<Integer> closeLandmarks = new ArrayList<Integer>(); 
			
//			Making a list of Landmarks that are close to the current Position and are within the right angle
			for (int nodes=0; nodes<cn.getSize()-1; nodes++) {
				Location checkLocation = new Location ("x");
				checkLocation.setLatitude(cn.getDlati(nodes));
				checkLocation.setLongitude(cn.getDlongi(nodes));
				
				if ((thisLocation.distanceTo(checkLocation) < 25) && (cn.getIs_uni_landmark(nodes)==true) 
						&& checkLandmarks (currentNodePosition, myTrip, cn, thisLocation, nodes)==true) {
					closeLandmarks.add(nodes);


					
				}
				
			}
			
			
			
			int bestLmID=0; 
			int currentRank=10; 
			for (int lm=0; lm < closeLandmarks.size(); lm++) {
				if (cn.getLmrank(closeLandmarks.get(lm)) < currentRank) {
					currentRank= cn.getLmrank(closeLandmarks.get(lm));
					bestLmID = closeLandmarks.get(lm);

				}
				
				if (cn.getLmrank(closeLandmarks.get(lm)) == currentRank) {
					Location checkLocation1 = new Location ("x");
					checkLocation1.setLatitude(cn.getDlati(closeLandmarks.get(lm)));
					checkLocation1.setLongitude(cn.getDlongi(closeLandmarks.get(lm)));
					Location checkLocation2 = new Location ("x");
					checkLocation2.setLatitude(cn.getDlati(bestLmID));
					checkLocation2.setLongitude(cn.getDlongi(bestLmID));
					
					if (thisLocation.distanceTo(checkLocation1) < thisLocation.distanceTo(checkLocation2)) {
						currentRank= cn.getLmrank(closeLandmarks.get(lm));
						bestLmID = closeLandmarks.get(lm);
					}
				}
				
			}
			
		return bestLmID; 	
		}
		
		
		public String showSurface (CustomNodes cn, Trip myTrip, int currentNodePosition) {
			
			String surface = ""; 
			
			currentNodeID=myTrip.getTripItem(currentNodePosition);
			nextNodeID=myTrip.getTripItem(currentNodePosition+1);
			boolean match=false; 
			boolean currentHasName=false; 
			boolean currentHasSurface=false;
			boolean nextHasName=false;
			boolean nextHasSurface=false;
			boolean currentHasSteps=false;
			boolean nextHasSteps=false;
			String currentSurfaceValue=" "; 
			String currentNameValue=" ";
			String nextSurfaceValue=" "; 
			String nextNameValue=" ";
			
			for (int i=0; i<cn.getValueSize(currentNodeID); i++) {
				if ((cn.getTag(currentNodeID, i)).equals("name")) {
					currentHasName=true;
					currentNameValue=cn.getValue(currentNodeID, i);
					Log.i(TAG, "showSurface, currentName: " + currentNameValue);
				}
				if ((cn.getTag(currentNodeID, i)).equals("surface")) {
					currentHasSurface=true; 
					currentSurfaceValue=cn.getValue(currentNodeID, i);
					Log.i(TAG, "showSurface, currentSurface: " + currentSurfaceValue);
				}
				
				if ((cn.getTag(currentNodeID, i)).equals("highway") 
						&& cn.getValue(currentNodeID, i).equals("steps")) {
					currentHasSteps = true; 
				}
				
			}
			
			for (int i=0; i<cn.getValueSize(nextNodeID); i++) {
				if ((cn.getTag(nextNodeID, i)).equals("name")) {
					nextHasName=true; 
					nextNameValue=cn.getValue(nextNodeID, i);
					Log.i(TAG, "showSurface, nextName: " + nextNameValue);
				}
				if ((cn.getTag(nextNodeID, i)).equals("surface")) {
					nextHasSurface=true; 
					nextSurfaceValue=cn.getValue(nextNodeID, i);
					Log.i(TAG, "showSurface, nextSurface: " + nextSurfaceValue);
				}
				
				if ((cn.getTag(nextNodeID, i)).equals("highway") 
						&& cn.getValue(nextNodeID, i).equals("steps")) {
					nextHasSteps = true; 
				}
			}
			
			
			
			
			if ((currentHasName==true) && (nextHasName==true) && ((currentNameValue).equals(nextNameValue))) {
				surface = (" weiter auf " + nextNameValue);
			}
			
			else if ((currentHasSurface==true) && (nextHasSurface==true) && ((currentSurfaceValue).equals(nextSurfaceValue))) {
				surface = (" weiter auf " + nextSurfaceValue);
			}
			
			if (currentHasSteps && nextHasSteps) {
				surface = surface.concat(" auf Treppen");
			}
			
			else if (nextHasSteps){
				surface = surface.concat(" Richtung Treppen");
			}
			
			Log.d(TAG, "showSurface returns: " + surface);
			return surface; 
			
		}

		
		
//		This looks for Tags in the current Node and the Nodes to come and puts together the description for the user
		public void showDescriptions (int currentNodePosition, Trip myTrip, CustomNodes cn, TextView myText, Location thisLocation) {
			
			ArrayList<String> currentNodeStringList = new ArrayList<String>();
			if (cn.getHas_tags(currentNodeID) == true) {
				
				
				
				for (int i=0; i<cn.getValueSize(currentNodeID); i++) {
					if ((cn.getTag(currentNodeID, i).equals("name"))) {
//							|| (cn.getTag(currentNodeID, i).equals("surface")) || (cn.getTag(currentNodeID, i).equals("highway"))) {
					currentNodeStringList.add(cn.getValue(currentNodeID, i));
					}
				}
			}
		
			myText.setSingleLine(false);
			myText.setText("Weiter auf: ");	
			for (int j=0; j<currentNodeStringList.size(); j++) {
				myText.append(currentNodeStringList.get(j));
				myText.append (" ");
			}
			myText.append("\n");
	
			if (cn.getHas_tag_from_lm(currentNodeID)==true){
			
			}
		
		
		
//		Looking for Tags in the Nodes to come
			ArrayList<String> nextNodesStringList = new ArrayList<String>();
			myText.append("Richtung: ");	
			for (int j=0; j<nextNodesStringList.size(); j++) {
	
					myText.append(nextNodesStringList.get(j));
					myText.append (" ");
			}
			myText.append ("\n");
				
		
		
		
	//		Appending the compass direction of the next Node
			nextNodePosition=currentNodePosition+1;
			if (!(currentNodePosition==myTrip.getTripList().size()-1)) {
				Location nextLocation=new Location ("x");
				nextLocation.setLatitude(cn.getDlati(myTrip.getTripItem(nextNodePosition)));
				nextLocation.setLongitude(cn.getDlongi(myTrip.getTripItem(nextNodePosition)));
				Compass myCompass = new Compass();
				myText.append ("Richtung: " + myCompass.getOrientation(thisLocation, nextLocation));
			}
		
		}
		
		public boolean checkForDestination (CustomNodes cn, MyLocationOverlay myLocOverlay, Trip myTrip) {
		
			Location thisLocation = myLocOverlay.getLastFix();
			
			if (thisLocation == null) {
				return false; 
			}
			
			
			Location destLocation = new Location ("x");
			destLocation.setLatitude(cn.getDlati(myTrip.getTripItem(myTrip.getTripList().size()-1)));
			destLocation.setLongitude(cn.getDlongi(myTrip.getTripItem(myTrip.getTripList().size()-1)));
//			Log.i(TAG, "DIst: "+ thisLocation.distanceTo(destLocation));
			if (thisLocation.distanceTo(destLocation) < 20) {
				finish=true;
				
			}
//			Log.i(TAG, "Finish: " + finish);
			return finish;
			
		}
		
		
//		Checks the Nodes that have already been passed by
				public void checkItems (CustomNodes cn, Trip myTrip, Location thisLocation) {
					Location checkLocation=new Location("x");
					
					for (int i=0; i<myTrip.getTripList().size(); i++){
						
						checkLocation.setLatitude(cn.getDlati(myTrip.getTripItem(i)));
						checkLocation.setLongitude(cn.getDlongi(myTrip.getTripItem(i)));
						
						if(thisLocation.distanceTo(checkLocation) < 10) {
							myTrip.setCheckItem(myTrip.getPosition(myTrip.getTripItem(i)));
							
						}
					
					}
					
				}


//		Send update to main activity
		public void update(Handler myHandler, int currentNodePosition, Trip myTrip, int currentLM, String output, boolean finish, boolean landmarkShown){
			Bundle myBundle= new Bundle();
			Message myMessage= new Message();
			myBundle.putInt("currentNodePosition", currentNodePosition);
			myBundle.putInt("currrentLM", currentLM);
			myBundle.putString("output", output);
			myBundle.putBoolean("finish", finish);
			myBundle.putBoolean("landmarkshown", landmarkShown);
			myMessage.setData(myBundle);
			myHandler.sendMessage(myMessage);
			
		}
		
//		Checks if the Landmark is within the direction of the next Node so people dont get landmarks that they have already passed 
		public boolean checkLandmarks (int currentNodePosition, Trip myTrip, CustomNodes cn, Location thisLocation, int nodes) {
			boolean valid= false; 
			
//			Location targetLocation = new Location("x");
//			targetLocation.setLatitude(cn.getDlati(myTrip.getTripItem(myTrip.getTripList().size()-1)));
//			targetLocation.setLongitude(cn.getDlongi(myTrip.getTripItem(myTrip.getTripList().size()-1)));
			
			if (!(currentNodePosition==myTrip.getTripList().size()-1)) {
				Location nextLocation = new Location("x");
				nextLocation.setLatitude(cn.getDlati(myTrip.getTripItem(currentNodePosition+1)));
				nextLocation.setLongitude(cn.getDlongi(myTrip.getTripItem(currentNodePosition+1)));
				
				Location lmLocation = new Location("x");
				lmLocation.setLatitude(cn.getDlati(nodes));
				lmLocation.setLongitude(cn.getDlongi(nodes));
				
				float btN = thisLocation.bearingTo(nextLocation);
				float btLm = thisLocation.bearingTo(lmLocation);
				
				Compass myCompass = new Compass();
				
				if (myCompass.correctAngle90(btN, btLm) == true) {
					valid = true; 
				}
			}
			
			return valid; 
		}

		
		public void prepare(Trip myTrip, CustomNodes cn, MyLocationOverlay myLocOverlay) {
			
			ArrayList<Segment> segments = myTrip.getSegments();
			this.segments = segments; 
			
			for (Segment s : segments) {
				
				segmentStarts.add(s.getNodes().get(0)); 
				
			}
			
			this.cn = cn; 
			this.myTrip = myTrip; 
			this.myLocOverlay = myLocOverlay; 
			
			
		}
		
		public void checkCurrentSegment() {
			
			if (currentSegment == segmentStarts.size()-1) {
				return; 
			}
			
			
			
			
			int nextSegStartID = segmentStarts.get(currentSegment+1).getId();
			
			Location thisLoc = myLocOverlay.getLastFix(); 
			
			if (thisLoc == null) {
				return; 
			}
			
			Location nextSegStartLoc = new Location("x");
			 
			nextSegStartLoc.setLatitude(cn.getDlati(nextSegStartID));
			nextSegStartLoc.setLongitude(cn.getDlongi(nextSegStartID));
			
			if (thisLoc.distanceTo(nextSegStartLoc) < 10) {
				
				currentSegment = currentSegment+1; 
				
			}
			
			
		}
		
		public void checkCurrentSegmentTest() {
			
			if (currentSegment == segmentStarts.size()-1) {
				return; 
			}
			
			
			
			
			
			
			Location thisLoc = myLocOverlay.getLastFix(); 
			
			if (thisLoc == null) {
				return; 
			}
			
			
			for (int n=0; n<segmentStarts.size(); n++) {
				
				Location nodeLoc = new Location("x");
				nodeLoc.setLatitude(cn.getDlati(segmentStarts.get(n).getId()));
				nodeLoc.setLongitude(cn.getDlongi(segmentStarts.get(n).getId())); 
				
				if (thisLoc.distanceTo(nodeLoc) < 10) {
					
					currentSegment = n; 
					
				}
				
				
			}
			


			

			
			
		}

		
		
}

